#include "gc.h"


void debug_graph_connection (Graph3D const& graph, int startSliceNo, int layerNum)
{
  // For debug
  std::cout << "DEBUG INFO ****************************************" << std::endl;
  std::cout << "Slice No (-1 to quit): ";
  int dbSliceNo = -1;
  std::cin >> dbSliceNo;
  while (dbSliceNo != -1) {
    std::cout << "Component No: ";
    int dbComponentNo = -1;
    std::cin >> dbComponentNo;
    std::cout << "End Node Slice No (0 - all; 1 - adjacent; 2 - skip; -1 - reverse adjacent; -2 - reverse skip): ";
    int dbEndNodeSliceNo = 0;
    std::cin >> dbEndNodeSliceNo;

    if (dbEndNodeSliceNo == 0) {
      if (dbSliceNo - startSliceNo < layerNum - 1) {
	std::cout << "Adjacent: " << std::endl;
	for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].edges.begin(); 
	     itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].edges.end(); itr++) {
	  std::string hstatus;
	  std::string tstatus;
	  if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
	    hstatus = " (N)";
	  }
	  else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
	    hstatus = " (D)";
	  }
	  if (graph.nodes[dbSliceNo - startSliceNo + 1][itr->endNodeNo].status == NODE_NORMAL) {
	    tstatus = " (N)";
	  }
	  else if (graph.nodes[dbSliceNo - startSliceNo + 1][itr->endNodeNo].status == NODE_DELETED) {
	    tstatus = " (D)";
	  }
	  std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
		    << itr->endNodeNo << tstatus << " @ " << dbSliceNo + 1 << ":\n"
		    << "\ta = " << itr->area << ", wa = " << itr->weight_area 
		    << "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
		    << "\n\tw = " << itr->weight << std::endl;
	}
      }
      if (dbSliceNo - startSliceNo < layerNum - 2) {
	std::cout << "Skip: " << std::endl;
	for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].skipEdges.begin(); 
	     itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].skipEdges.end(); itr++) {
	  std::string hstatus;
	  std::string tstatus;
	  if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
	    hstatus = " (N)";
	  }
	  else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
	    hstatus = " (D)";
	  }
	  if (graph.nodes[dbSliceNo - startSliceNo + 2][itr->endNodeNo].status == NODE_NORMAL) {
	    tstatus = " (N)";
	  }
	  else if (graph.nodes[dbSliceNo - startSliceNo + 2][itr->endNodeNo].status == NODE_DELETED) {
	    tstatus = " (D)";
	  }
	  std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
		    << itr->endNodeNo << tstatus << " @ " << dbSliceNo + 2 << ":\n"
		    << "\ta = " << itr->area << ", wa = " << itr->weight_area 
		    << "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
		    << "\n\tw = " << itr->weight << std::endl;
	}
      }
      if (dbSliceNo - startSliceNo > 0) {
	std::cout << "Reverse adjacent: " << std::endl;
	for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseEdges.begin(); 
	     itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseEdges.end(); itr++) {
	  std::string hstatus;
	  std::string tstatus;
	  if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
	    hstatus = " (N)";
	  }
	  else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
	    hstatus = " (D)";
	  }
	  if (graph.nodes[dbSliceNo - startSliceNo - 1][itr->endNodeNo].status == NODE_NORMAL) {
	    tstatus = " (N)";
	  }
	  else if (graph.nodes[dbSliceNo - startSliceNo - 1][itr->endNodeNo].status == NODE_DELETED) {
	    tstatus = " (D)";
	  }
	  std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
		    << itr->endNodeNo << tstatus << " @ " << dbSliceNo - 1 << ":\n"
		    << "\ta = " << itr->area << ", wa = " << itr->weight_area 
		    << "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
		    << "\n\tw = " << itr->weight << std::endl;
	}
      }
      if (dbSliceNo - startSliceNo > 1) {
	std::cout << "Reverse skip: " << std::endl;
	for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseSkipEdges.begin(); 
	     itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseSkipEdges.end(); itr++) {
	  std::string hstatus;
	  std::string tstatus;
	  if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
	    hstatus = " (N)";
	  }
	  else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
	    hstatus = " (D)";
	  }
	  if (graph.nodes[dbSliceNo - startSliceNo - 2][itr->endNodeNo].status == NODE_NORMAL) {
	    tstatus = " (N)";
	  }
	  else if (graph.nodes[dbSliceNo - startSliceNo - 2][itr->endNodeNo].status == NODE_DELETED) {
	    tstatus = " (D)";
	  }
	  std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
		    << itr->endNodeNo << tstatus << " @ " << dbSliceNo - 2 << ":\n"
		    << "\ta = " << itr->area << ", wa = " << itr->weight_area 
		    << "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
		    << "\n\tw = " << itr->weight << std::endl;
	}
      }
    }
    else {
      std::cout << "End Node Component No (-1 - all): ";
      int dbEndNodeComponentNo = -2;
      std::cin >> dbEndNodeComponentNo;
      if (dbEndNodeSliceNo == 1) {
	if (dbEndNodeComponentNo == -1) {
	  for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].edges.begin(); 
	       itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].edges.end(); itr++) {
	    std::string hstatus;
	    std::string tstatus;
	    if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
	      hstatus = " (N)";
	    }
	    else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
	      hstatus = " (D)";
	    }
	    if (graph.nodes[dbSliceNo - startSliceNo + 1][itr->endNodeNo].status == NODE_NORMAL) {
	      tstatus = " (N)";
	    }
	    else if (graph.nodes[dbSliceNo - startSliceNo + 1][itr->endNodeNo].status == NODE_DELETED) {
	      tstatus = " (D)";
	    }
	    std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
		      << itr->endNodeNo << tstatus << " @ " << dbSliceNo + 1 << ":\n"
		      << "\ta = " << itr->area << ", wa = " << itr->weight_area 
		      << "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
		      << "\n\tw = " << itr->weight << std::endl;
	    // std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
	    // 	      << itr->endNodeNo << tstatus << " @ " << dbSliceNo + 1 << ": " 
	    // 	      << "a = " << itr->area << ", c = " << itr->correlation 
	    // 	      << ", wa = " << itr->weight_area << ", wc = " << itr->weight_correlation 
	    // 	      << ", w = " << itr->weight << std::endl;
	  }
	}
	else {
	  for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].edges.begin(); 
	       itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].edges.end(); itr++) {
	    if (itr->endNodeNo == dbEndNodeComponentNo) {
	      std::string hstatus;
	      std::string tstatus;
	      if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
		hstatus = " (N)";
	      }
	      else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
		hstatus = " (D)";
	      }
	      if (graph.nodes[dbSliceNo - startSliceNo + 1][itr->endNodeNo].status == NODE_NORMAL) {
		tstatus = " (N)";
	      }
	      else if (graph.nodes[dbSliceNo - startSliceNo + 1][itr->endNodeNo].status == NODE_DELETED) {
		tstatus = " (D)";
	      }
	      std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
			<< itr->endNodeNo << tstatus << " @ " << dbSliceNo + 1 << ":\n"
			<< "\ta = " << itr->area << ", wa = " << itr->weight_area 
			<< "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
			<< "\n\tw = " << itr->weight << std::endl;
	      // std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
	      // 		<< itr->endNodeNo << tstatus << " @ " << dbSliceNo + 1 << ": " 
	      // 		<< "a = " << itr->area << ", c = " << itr->correlation 
	      // 		<< ", wa = " << itr->weight_area << ", wc = " << itr->weight_correlation 
	      // 		<< ", w = " << itr->weight << std::endl;
	    }
	  }
	}
      }
      else if (dbEndNodeSliceNo == 2) {
	if (dbEndNodeComponentNo == -1) {
	  for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].skipEdges.begin(); 
	       itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].skipEdges.end(); itr++) {
	    std::string hstatus;
	    std::string tstatus;
	    if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
	      hstatus = " (N)";
	    }
	    else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
	      hstatus = " (D)";
	    }
	    if (graph.nodes[dbSliceNo - startSliceNo + 2][itr->endNodeNo].status == NODE_NORMAL) {
	      tstatus = " (N)";
	    }
	    else if (graph.nodes[dbSliceNo - startSliceNo + 2][itr->endNodeNo].status == NODE_DELETED) {
	      tstatus = " (D)";
	    }
	    std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
		      << itr->endNodeNo << tstatus << " @ " << dbSliceNo + 2 << ":\n"
		      << "\ta = " << itr->area << ", wa = " << itr->weight_area 
		      << "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
		      << "\n\tw = " << itr->weight << std::endl;
	    // std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
	    // 	      << itr->endNodeNo << tstatus << " @ " << dbSliceNo + 2 << ": " 
	    // 	      << "a = " << itr->area << ", c = " << itr->correlation 
	    // 	      << ", wa = " << itr->weight_area << ", wc = " << itr->weight_correlation 
	    // 	      << ", w = " << itr->weight << std::endl;
	  }
	}
	else {
	  for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].skipEdges.begin(); 
	       itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].skipEdges.end(); itr++) {
	    if (itr->endNodeNo == dbEndNodeComponentNo) {
	      std::string hstatus;
	      std::string tstatus;
	      if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
		hstatus = " (N)";
	      }
	      else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
		hstatus = " (D)";
	      }
	      if (graph.nodes[dbSliceNo - startSliceNo + 2][itr->endNodeNo].status == NODE_NORMAL) {
		tstatus = " (N)";
	      }
	      else if (graph.nodes[dbSliceNo - startSliceNo + 2][itr->endNodeNo].status == NODE_DELETED) {
		tstatus = " (D)";
	      }
	      std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
			<< itr->endNodeNo << tstatus << " @ " << dbSliceNo + 2 << ":\n"
			<< "\ta = " << itr->area << ", wa = " << itr->weight_area 
			<< "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
			<< "\n\tw = " << itr->weight << std::endl;
	      // std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
	      // 		<< itr->endNodeNo << tstatus << " @ " << dbSliceNo + 2 << ": " 
	      // 		<< "a = " << itr->area << ", c = " << itr->correlation 
	      // 		<< ", wa = " << itr->weight_area << ", wc = " << itr->weight_correlation 
	      // 		<< ", w = " << itr->weight << std::endl;
	    }
	  }
	}
      }
      else if (dbEndNodeSliceNo == -1) {
	if (dbEndNodeComponentNo == -1) {
	  for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseEdges.begin(); 
	       itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseEdges.end(); itr++) {
	    std::string hstatus;
	    std::string tstatus;
	    if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
	      hstatus = " (N)";
	    }
	    else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
	      hstatus = " (D)";
	    }
	    if (graph.nodes[dbSliceNo - startSliceNo - 1][itr->endNodeNo].status == NODE_NORMAL) {
	      tstatus = " (N)";
	    }
	    else if (graph.nodes[dbSliceNo - startSliceNo - 1][itr->endNodeNo].status == NODE_DELETED) {
	      tstatus = " (D)";
	    }
	    std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
		      << itr->endNodeNo << tstatus << " @ " << dbSliceNo - 1 << ":\n"
		      << "\ta = " << itr->area << ", wa = " << itr->weight_area 
		      << "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
		      << "\n\tw = " << itr->weight << std::endl;
	    // std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
	    // 	      << itr->endNodeNo << tstatus << " @ " << dbSliceNo - 1 << ": " 
	    // 	      << "a = " << itr->area << ", c = " << itr->correlation 
	    // 	      << ", wa = " << itr->weight_area << ", wc = " << itr->weight_correlation 
	    // 	      << ", w = " << itr->weight << std::endl;
	  }
	}
	else {
	  for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseEdges.begin(); 
	       itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseEdges.end(); itr++) {
	    if (itr->endNodeNo == dbEndNodeComponentNo) {
	      std::string hstatus;
	      std::string tstatus;
	      if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
		hstatus = " (N)";
	      }
	      else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
		hstatus = " (D)";
	      }
	      if (graph.nodes[dbSliceNo - startSliceNo - 1][itr->endNodeNo].status == NODE_NORMAL) {
		tstatus = " (N)";
	      }
	      else if (graph.nodes[dbSliceNo - startSliceNo - 1][itr->endNodeNo].status == NODE_DELETED) {
		tstatus = " (D)";
	      }
	      std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
			<< itr->endNodeNo << tstatus << " @ " << dbSliceNo - 1 << ":\n"
			<< "\ta = " << itr->area << ", wa = " << itr->weight_area 
			<< "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
			<< "\n\tw = " << itr->weight << std::endl;
	      // std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " -> " 
	      // 		<< itr->endNodeNo << tstatus << " @ " << dbSliceNo - 1 << ": " 
	      // 		<< "a = " << itr->area << ", c = " << itr->correlation 
	      // 		<< ", wa = " << itr->weight_area << ", wc = " << itr->weight_correlation 
	      // 		<< ", w = " << itr->weight << std::endl;
	    }
	  }
	}
      }
      else if (dbEndNodeSliceNo == -2) {
	if (dbEndNodeComponentNo == -1) {
	  for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseSkipEdges.begin(); 
	       itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseSkipEdges.end(); itr++) {
	    std::string hstatus;
	    std::string tstatus;
	    if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
	      hstatus = " (N)";
	    }
	    else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
	      hstatus = " (D)";
	    }
	    if (graph.nodes[dbSliceNo - startSliceNo - 2][itr->endNodeNo].status == NODE_NORMAL) {
	      tstatus = " (N)";
	    }
	    else if (graph.nodes[dbSliceNo - startSliceNo - 2][itr->endNodeNo].status == NODE_DELETED) {
	      tstatus = " (D)";
	    }
	    std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
		      << itr->endNodeNo << tstatus << " @ " << dbSliceNo - 2 << ":\n"
		      << "\ta = " << itr->area << ", wa = " << itr->weight_area 
		      << "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
		      << "\n\tw = " << itr->weight << std::endl;
	    // std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
	    // 	      << itr->endNodeNo << tstatus << " @ " << dbSliceNo - 2 << ": " 
	    // 	      << "a = " << itr->area << ", c = " << itr->correlation 
	    // 	      << ", wa = " << itr->weight_area << ", wc = " << itr->weight_correlation 
	    // 	      << ", w = " << itr->weight << std::endl;
	  }
	}
	else {
	  for (NodeEdgeSet::const_iterator itr = graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseSkipEdges.begin(); 
	       itr != graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].reverseSkipEdges.end(); itr++) {
	    if (itr->endNodeNo == dbEndNodeComponentNo) {
	      std::string hstatus;
	      std::string tstatus;
	      if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_NORMAL) {
		hstatus = " (N)";
	      }
	      else if (graph.nodes[dbSliceNo - startSliceNo][dbComponentNo].status == NODE_DELETED) {
		hstatus = " (D)";
	      }
	      if (graph.nodes[dbSliceNo - startSliceNo - 2][itr->endNodeNo].status == NODE_NORMAL) {
		tstatus = " (N)";
	      }
	      else if (graph.nodes[dbSliceNo - startSliceNo - 2][itr->endNodeNo].status == NODE_DELETED) {
		tstatus = " (D)";
	      }
	      std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
			<< itr->endNodeNo << tstatus << " @ " << dbSliceNo - 2 << ":\n"
			<< "\ta = " << itr->area << ", wa = " << itr->weight_area 
			<< "\n\tc = " << itr->correlation << ", wc = " << itr->weight_correlation 
			<< "\n\tw = " << itr->weight << std::endl;
	      // std::cout << dbComponentNo << hstatus << " @ " << dbSliceNo << " --> " 
	      // 		<< itr->endNodeNo << tstatus << " @ " << dbSliceNo - 2 << ": " 
	      // 		<< "a = " << itr->area << ", c = " << itr->correlation 
	      // 		<< ", wa = " << itr->weight_area << ", wc = " << itr->weight_correlation 
	      // 		<< ", w = " << itr->weight << std::endl;
	    }
	  }
	}
      }
    }
    std::cout << "Slice No (-1 to quit): ";
    std::cin >> dbSliceNo;
  }
  std::cout << "~DEBUG INFO ***************************************" << std::endl;
  assert(1 < 0);
}
